#include <p18cxxx.h>
#include "define.h"
 
void initialise_AD_converter(void); //set up the AD converter
void receive_setup(void); //Set registers to enable USART receive
void transmit_setup(void);    //Set registers to enable USART transmit
void keypad_setup(void);    // Set registers to enable external interrupt on PORTB
extern void initialise_LCD (void);
extern void spi_setup(void);
extern void tts_setup(void);
extern void tts_send_command(char* command, char* output);
 
extern unsigned int sampleInterval; /** Used in initialising the A/D, for the CCP2 compare. */
 
/**
 * Calls all initialisation functions and sets up the interrupts.
 *
 * Specifically, the LCD, A/D Converter, Serial receive, Serial transmit,
 * keypad, and TTS are all initialised.
 * @post All initialisations are complete
 */
void setup(void)
{
    INTCONbits.GIE = 0;        // Disable interrupts
 
    RCONbits.IPEN = 1; // Enable interrupt priority
 
 
    initialise_LVdetect(); //Start the Low Voltage detect sequence
    initialise_LCD();
    initialise_AD_converter(); //set up the AD converter
    transmit_setup();    //Set registers to enable USART transmit
    receive_setup();     //Set registers to enable USART receive
    keypad_setup();
 
    spi_setup();    //TTS
    tts_setup();    //TTS
 
    INTCONbits.GIEH = 1;// (IPEN = 1) -> enable high-priority interrupts globally
    INTCONbits.GIEL = 1; //(IPEN = 1) -> enable low-priority peripheral interrupts
 
    while(LVDCONbits.IRVST == 0)//Wait for LVD voltage to stablize
    {/*Do nothing and wait*/}
    //Once the Low voltage detect module is ready, reset the flag and then enable interrupts
    PIR2bits.LVDIF = 0; //Reset LVD interrupt flag in case it was accidentally set
 
    INTCONbits.GIE = 1;        // Enable Interrupts
}
 
 
/**
 * Sets up the serial receive system. This should be used in conjunction with
 * transmit_setup to enable the entire serial system.
 * @post The serial receive system is initialised and enabled
 */
void receive_setup(void)
{
    TRISCbits.TRISC6 = 0;        // PortC7 is output
 
    // Initialise RS232 RC - with interrupts
 
    PIR1bits.RCIF = 0;        // Clear RC flag
    PIE1bits.RCIE = 1;        // Enable RC interrupt.
    IPR1bits.RCIP = 1;        // High Priority for RC interrupts
 
    RCSTAbits.CREN = 1;        // Enable RC
 
    INTCONbits.PEIE = 1;
 
 
 
}
 
/**
 * Sets up the serial transmit system. This should be used in conjunction with
 * receive_setup to enable the entire serial system.
 * @post The serial transmit system is initialised and enabled
 */
void transmit_setup(void) //Setup function, or parameters to include in a central setup function
{
 
    TRISCbits.TRISC7 = 1;// PortC 7 is output
    TXSTAbits.SYNC = 0;// asynchronous mode
    TXSTAbits.BRGH = 1; //high baud rate
    SPBRG = 25;// for baud rate 9600
    TXSTAbits.TX9 = 0; //8-bit transmission
    TXSTAbits.TXEN = 1;// enable transmission
    RCSTAbits.SPEN = 1; //Enable serial port
    IPR1bits.TXIP = 0; //Low priority for transmit interrupt
 
}
 
/**
 * Initialises the keypad.
 *
 * The required ports and interrupts are configured such that the program
 * can receive and handle keypad inputs.
 * @post The keypad system is initialised
 */
void keypad_setup(void)
{
 
    PORTB= 0b00000000;            // Clear PORT B
    TRISB= 0b00111110;            // Set PORTB <1-5> to input
    INTCON3bits.INT1IP=1;        // Set Priority of external interrupt 1 to high
    INTCON3bits.INT1IE=1;        // enable external interrupt 1
    INTCON3bits.INT1IF=0;        // Clear external interrupt flag
    INTCON2bits.INTEDG1 =1;        // Set to trigger interrupt on rising edge
}
 
 
/**
 * Initialises the A/D converter, and waits until the A/D converter has finished enabling.
 * @post The A/D converter is enabled.
 */
void initialise_AD_converter(void)
{
 
    ADCON0 = 0b01000001;      //Fosc/8, A/D enabled
    ADCON0bits.CHS0 = 1;    //0 for pin A0, 1 for pin A1 IMPORTANT!
    //ADCON1 = 0b10001110;      //Right justify, 1 analog channel; VDD and VSS references
    ADCON1 = 0b10000101;      //Right justify, 1 analog channel; VDD and VSS references
    //PCFG = 0101: Pin A<3> is set to be the V++ reference, the board GND is the V-- refernce
   T0CON =  0b11000111;      //Timer 0 on, set to 8 bit, prescaler 1:256
 
    T3CON =  0b10111001;    //Set up timer 3, with x8 prescsaler
    PIE1bits.ADIE = 1;        //Enable A/D interrupt
    IPR1bits.ADIP = 0;        //Set A/D interrupt to low priority
 
    CCP2CON = 0b00001011;
    CCPR2 = sampleInterval;    //Initialise CCPR2
 
    TRISAbits.TRISA0 = 1; //Make sure that pin A0 is input
 
    while(INTCONbits.TMR0IF == 0);    //Wait for a while to allow A/D converter to start up
    INTCONbits.TMR0IF = 0;
    T0CON = 0;    //Reset TMR0 in case another module needs to use it
}
 
/**
 * Initialises the Low Voltage Detect, by powering up the LVD hardware
 * and configuring the registers and interrupts.
 * @post The Low Voltage Detect system is initialised and operational
 */
void initialise_LVdetect(void)
{
    LVDCON = 0b00110111; //Set trip voltage = 2.97-2.8V
    LVDCONbits.LVDEN = 1; //Power up the LVD hardware
    //Do not enable interrupt until voltage has stabalised
    PIR2bits.LVDIF = 0;
    PIE2bits.LVDIE = 1; //Enable LVD interrupt
}